<link rel="stylesheet" href="../../node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="../index.css">
<div class="container-fluid" id="app">
    <form rolw="form">
        <div class="row pt-2 align-items-center">
            <div class="col-2 text-end">编码：</div>
            <div class="col-4"><select class="form-select form-select-sm" v-model="encoding" @change="changeEncoding">
                <option value="NONE">请选择</option>
                <option v-for="(item, index) in encodings" :key="index" :value="item.code">{{item.text}}</option>
            </select></div>
            <div class="col"></div>
        </div>
        <div class="row pt-2">
            <div class="col-2 text-end">数据：</div>
            <div class="col-8">
                <textarea class="form-control form-control-sm" style="resize:none" rows="4" :placeholder="dataMsg" v-model="dataText"></textarea>
            </div>
            <div class="col"></div>
        </div>
        <div class="row pt-2 align-items-center">
            <div class="col-2"></div>
            <div class="col-2">
                <button type="button" class="btn btn-primary btn-sm" @click="createBarCode">生成条形码</button>
            </div>
            <div class="col">点击图片即可下载条形码</div>
        </div>
        <div class="row pt-2">
            <div class="col-2 text-end text-nowrap">条形码：</div>
            <div class="col"><img id="barcode" @click="download"></div>
        </div>
    </form>
</div>
<script src="../../node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="../../node_modules/jsbarcode/dist/JsBarcode.all.min.js"></script>
<script src="../../node_modules/vue/dist/vue.global.prod.js"></script>
<script>
const app = {
    data() {
        return {
            encodings: [
                {code: 'code128', text: 'Code 128', msg: 'CODE128码是广泛应用在企业内部管理、生产流程、物流控制系统方面的条码码制，可表示从 ASCII 0 到ASCII 127 共128个字符，故称128码。支持数字、大小写字母、普通符号及控制符，如：AB+cd-1234%'},
                {code: 'code128a', text: 'Code 128 A', msg: '标准数字和大写字母、控制符、特殊字符'},
                {code: 'code128b', text: 'Code 128 B', msg: '标准数字和大写字母、小写字母、特殊字符'},
                {code: 'code128c', text: 'Code 128 C', msg: '偶数个纯数字编码，[00]-[99]的数字对集合,共100个', check: /^(\d\d){0,}$/g},
                {code: 'ean2', text: 'EAN 2', msg: '仅支持2位数字', check: /^\d{2}$/g},
                {code: 'ean5', text: 'EAN 5', msg: 'EAN 5码共5位数字，它是EAN13条码用于书籍的一种补充,它被建议是用来提供的书籍的价格。', check: /^\d{5}$/g},
                {code: 'ean8', text: 'EAN 8', msg: 'EAN8缩短码（European Article Number欧洲物品编码）广泛用于商品条码，共8位数字，是EAN的简易编码形式。最后一位为校验位，由前面的12位或7位数字计算得出。', check: /^\d{8}$/g},
                {code: 'ean13', text: 'EAN 13', msg: 'EAN13标准码（European Article Number欧洲物品编码）广泛用于商品条码，共13位数字，是EAN的标准编码形式，系由「国家代码」3位数，「厂商代码」4位数，「产品代码」5位数，以及「校正码」1位数组成。最后一位校验位，由前面的12位或7位数字计算得出。', check: /^\d{13}$/g},
                {code: 'upc', text: 'UPC', msg: 'universal production code，商品通用条码，是一种长度固定、连续性的条码，UPC码仅可用来表示数字，故其字码集为数字0~9。'},
                {code: 'msi', text: 'MSI', msg: 'MSI或修改的Plessey是由MSI数据公司开发的条形码，主要用于仓库环境中的库存控制、标记存储容器和货架。仅支持数字0-9。', check: /^\d+$/g},
                {code: 'msi10', text: 'MSI10', msg: 'MSI 10 的自动校验和计算。仅支持数字0-9。', check: /^\d+$/g},
                {code: 'msi11', text: 'MSI11', msg: 'MSI 11 的自动校验和计算。仅支持数字0-9。', check: /^\d+$/g},
                {code: 'msi1010', text: 'MSI1010', msg: 'MSI 1010 的自动校验和计算。仅支持数字0-9。', check: /^\d+$/g},
                {code: 'msi1110', text: 'MSI1110', msg: 'MSI 1110 的自动校验和计算。仅支持数字0-9。', check: /^\d+$/g}
            ],
            encoding: 'NONE',
            dataMsg: '',
            dataText: ''
        }
    },
    created() {
        document.addEventListener('keyup', (e) => {
            if (e.ctrlKey && e.shiftKey && (e.key == 'I' || e.key ==  'i')) {
                parent.devTools();
            }
            if (e.ctrlKey && (e.key == 'r' || e.key == 'R')) {
                parent.refresh();
            }
        });
    },
    methods: {
        changeEncoding() {
            this.dataMsg = getItem(this.encodings, this.encoding).msg;
            document.getElementById('barcode').src = '';
        },
        createBarCode() {
            document.getElementById('barcode').src = '';
            console.info('encoding=========%s', this.encoding);
            if('NONE' == this.encoding) return;
            console.info('dataText=========%s', this.dataText)
            let item = getItem(this.encodings, this.encoding);
            console.info('%s===============%s', item.check, (new RegExp(item.check)).test(this.dataText))
            if(item.check != undefined && !(new RegExp(item.check)).test(this.dataText)) {
                return;
            }
            // JsBarcode('元素选择器','格式化文本', {选项});
            JsBarcode('#barcode', this.dataText, {
                format: this.encoding,
                displayValue: true
            })
        },
        download() {
            let fileName = 'barcode.png';
            let imgStr = document.getElementById('barcode').src.toString();
            // 图片下载感谢 [小黑ii](https://blog.csdn.net/qq_35844177?type=blog)：[js下载base64格式的图片](https://blog.csdn.net/qq_35844177/article/details/79094249)
            downloadFile(fileName, imgStr);
        }
    }
}
Vue.createApp(app).mount('#app');

function downloadFile(fileName, content) {
    let aLink = document.createElement('a');
    let blob = this.base64ToBlob(content); //new Blob([content]);

    let evt = document.createEvent("HTMLEvents");
    evt.initEvent("click", true, true);//initEvent 不加后两个参数在FF下会报错  事件类型，是否冒泡，是否阻止浏览器的默认行为
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);

    // aLink.dispatchEvent(evt);
    //aLink.click()
    aLink.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));//兼容火狐
}

function base64ToBlob(code) {
    let parts = code.split(';base64,');
    let contentType = parts[0].split(':')[1];
    let raw = window.atob(parts[1]);
    let rawLength = raw.length;

    let uInt8Array = new Uint8Array(rawLength);

    for (let i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], {type: contentType});
}

function getItem(array, code) {
    let i = '';
    for(let item of array) {
        if(code == item.code) {
            i = item;
            break;
        }
    }
    return i;
}
</script>